home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
MONITOR
/
HERKULES.ARJ
/
HERKULES.INC
< prev
Wrap
Text File
|
1989-10-30
|
49KB
|
1,044 lines
;+---------------------------------------------------------------------------+
;! IncludeFile zu !
;! HERKULES.ASM !
;+---------------------------------------------------------------------------+
;Hier zuerst die ZeichenSatz-Tabelle:
DB 000h,000h,000h,000h,000h,000h,000h,000h
DB 07Eh,081h,0A5h,081h,0BDh,099h,081h,07Eh
DB 07Eh,0FFh,0DBh,0FFh,0C3h,0E7h,0FFh,07Eh
DB 06Ch,0FEh,0FEh,0FEh,07Ch,038h,010h,000h
DB 010h,038h,07Ch,0FEh,07Ch,038h,010h,000h
DB 038h,07Ch,038h,0FEh,0FEh,07Ch,038h,07Ch
DB 010h,010h,038h,07Ch,0FEh,07Ch,038h,07Ch
DB 000h,000h,018h,03Ch,03Ch,018h,000h,000h
DB 0FFh,0FFh,0E7h,0C3h,0C3h,0E7h,0FFh,0FFh
DB 000h,03Ch,066h,042h,042h,066h,03Ch,000h
DB 0FFh,0C3h,099h,0BDh,0BDh,099h,0C3h,0FFh
DB 00Fh,007h,00Fh,07Dh,0CCh,0CCh,0CCh,078h
DB 03Ch,066h,066h,066h,03Ch,018h,07Eh,018h
DB 03Fh,033h,03Fh,030h,030h,070h,0F0h,0E0h
DB 07Fh,063h,07Fh,063h,063h,067h,0E6h,0C0h
DB 099h,05Ah,03Ch,0E7h,0E7h,03Ch,05Ah,099h
DB 080h,0E0h,0F8h,0FEh,0F8h,0E0h,080h,000h
DB 002h,00Eh,03Eh,0FEh,03Eh,00Eh,002h,000h
DB 018h,03Ch,07Eh,018h,018h,07Eh,03Ch,018h
DB 066h,066h,066h,066h,066h,000h,066h,000h
DB 07Fh,0DBh,0DBh,07Bh,01Bh,01Bh,01Bh,000h
DB 03Eh,063h,038h,06Ch,06Ch,038h,0CCh,078h
DB 000h,000h,000h,000h,07Eh,07Eh,07Eh,000h
DB 018h,03Ch,07Eh,018h,07Eh,03Ch,018h,0FFh
DB 018h,03Ch,07Eh,018h,018h,018h,018h,000h
DB 018h,018h,018h,018h,07Eh,03Ch,018h,000h
DB 000h,018h,00Ch,0FEh,00Ch,018h,000h,000h
DB 000h,030h,060h,0FEh,060h,030h,000h,000h
DB 000h,000h,0C0h,0C0h,0C0h,0FEh,000h,000h
DB 000h,024h,066h,0FFh,066h,024h,000h,000h
DB 000h,018h,03Ch,07Eh,0FFh,0FFh,000h,000h
DB 000h,0FFh,0FFh,07Eh,03Ch,018h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h
DB 030h,078h,078h,078h,030h,000h,030h,000h
DB 06Ch,06Ch,06Ch,000h,000h,000h,000h,000h
DB 06Ch,06Ch,0FEh,06Ch,0FEh,06Ch,06Ch,000h
DB 030h,07Ch,0C0h,078h,00Ch,0F8h,030h,000h
DB 000h,0C6h,0CCh,018h,030h,066h,0C6h,000h
DB 038h,06Ch,038h,076h,0DCh,0CCh,076h,000h
DB 060h,060h,0C0h,000h,000h,000h,000h,000h
DB 018h,030h,060h,060h,060h,030h,018h,000h
DB 060h,030h,018h,018h,018h,030h,060h,000h
DB 000h,066h,03Ch,0FFh,03Ch,066h,000h,000h
DB 000h,030h,030h,0FCh,030h,030h,000h,000h
DB 000h,000h,000h,000h,000h,030h,030h,060h
DB 000h,000h,000h,0FCh,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,030h,030h,000h
DB 006h,00Ch,018h,030h,060h,0C0h,080h,000h
DB 07Ch,0C6h,0CEh,0DEh,0F6h,0E6h,07Ch,000h
DB 030h,070h,030h,030h,030h,030h,0FCh,000h
DB 078h,0CCh,00Ch,038h,060h,0CCh,0FCh,000h
DB 078h,0CCh,00Ch,038h,00Ch,0CCh,078h,000h
DB 01Ch,03Ch,06Ch,0CCh,0FEh,00Ch,01Eh,000h
DB 0FCh,0C0h,0F8h,00Ch,00Ch,0CCh,078h,000h
DB 038h,060h,0C0h,0F8h,0CCh,0CCh,078h,000h
DB 0FCh,0CCh,00Ch,018h,030h,030h,030h,000h
DB 078h,0CCh,0CCh,078h,0CCh,0CCh,078h,000h
DB 078h,0CCh,0CCh,07Ch,00Ch,018h,070h,000h
DB 000h,030h,030h,000h,000h,030h,030h,000h
DB 000h,030h,030h,000h,000h,030h,030h,060h
DB 018h,030h,060h,0C0h,060h,030h,018h,000h
DB 000h,000h,0FCh,000h,000h,0FCh,000h,000h
DB 060h,030h,018h,00Ch,018h,030h,060h,000h
DB 078h,0CCh,00Ch,018h,030h,000h,030h,000h
DB 07Ch,0C6h,0DEh,0DEh,0DEh,0C0h,078h,000h
DB 030h,078h,0CCh,0CCh,0FCh,0CCh,0CCh,000h
DB 0FCh,066h,066h,07Ch,066h,066h,0FCh,000h
DB 03Ch,066h,0C0h,0C0h,0C0h,066h,03Ch,000h
DB 0F8h,06Ch,066h,066h,066h,06Ch,0F8h,000h
DB 07Eh,060h,060h,078h,060h,060h,07Eh,000h
DB 07Eh,060h,060h,078h,060h,060h,060h,000h
DB 03Ch,066h,0C0h,0C0h,0CEh,066h,03Eh,000h
DB 0CCh,0CCh,0CCh,0FCh,0CCh,0CCh,0CCh,000h
DB 078h,030h,030h,030h,030h,030h,078h,000h
DB 01Eh,00Ch,00Ch,00Ch,0CCh,0CCh,078h,000h
DB 0E6h,066h,06Ch,078h,06Ch,066h,0E6h,000h
DB 060h,060h,060h,060h,060h,060h,07Eh,000h
DB 0C6h,0EEh,0FEh,0FEh,0D6h,0C6h,0C6h,000h
DB 0C6h,0E6h,0F6h,0DEh,0CEh,0C6h,0C6h,000h
DB 038h,06Ch,0C6h,0C6h,0C6h,06Ch,038h,000h
DB 0FCh,066h,066h,07Ch,060h,060h,0F0h,000h
DB 078h,0CCh,0CCh,0CCh,0DCh,078h,01Ch,000h
DB 0FCh,066h,066h,07Ch,06Ch,066h,0E6h,000h
DB 078h,0CCh,0E0h,070h,01Ch,0CCh,078h,000h
DB 0FCh,030h,030h,030h,030h,030h,030h,000h
DB 0CCh,0CCh,0CCh,0CCh,0CCh,0CCh,0FCh,000h
DB 0CCh,0CCh,0CCh,0CCh,0CCh,078h,030h,000h
DB 0C6h,0C6h,0C6h,0D6h,0FEh,0EEh,0C6h,000h
DB 0C6h,0C6h,06Ch,038h,038h,06Ch,0C6h,000h
DB 0CCh,0CCh,0CCh,078h,030h,030h,078h,000h
DB 0FEh,006h,00Ch,018h,030h,060h,0FEh,000h
DB 078h,060h,060h,060h,060h,060h,078h,000h
DB 0C0h,060h,030h,018h,00Ch,006h,002h,000h
DB 078h,018h,018h,018h,018h,018h,078h,000h
DB 010h,038h,06Ch,0C6h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,0FFh
DB 030h,030h,018h,000h,000h,000h,000h,000h
DB 000h,000h,078h,00Ch,07Ch,0CCh,076h,000h
DB 0E0h,060h,060h,07Ch,066h,066h,0DCh,000h
DB 000h,000h,078h,0CCh,0C0h,0CCh,078h,000h
DB 01Ch,00Ch,00Ch,07Ch,0CCh,0CCh,076h,000h
DB 000h,000h,078h,0CCh,0FCh,0C0h,078h,000h
DB 038h,06Ch,060h,0F0h,060h,060h,0F0h,000h
DB 000h,000h,076h,0CCh,0CCh,07Ch,00Ch,0F8h
DB 0E0h,060h,06Ch,076h,066h,066h,0E6h,000h
DB 030h,000h,070h,030h,030h,030h,078h,000h
DB 00Ch,000h,00Ch,00Ch,00Ch,0CCh,0CCh,078h
DB 0E0h,060h,066h,06Ch,078h,06Ch,0E6h,000h
DB 070h,030h,030h,030h,030h,030h,078h,000h
DB 000h,000h,0CCh,0FEh,0FEh,0D6h,0C6h,000h
DB 000h,000h,0F8h,0CCh,0CCh,0CCh,0CCh,000h
DB 000h,000h,078h,0CCh,0CCh,0CCh,078h,000h
DB 000h,000h,0DCh,066h,066h,07Ch,060h,0F0h
DB 000h,000h,076h,0CCh,0CCh,07Ch,00Ch,01Eh
DB 000h,000h,0DCh,076h,066h,060h,0F0h,000h
DB 000h,000h,07Ch,0C0h,078h,00Ch,0F8h,000h
DB 010h,030h,07Ch,030h,030h,034h,018h,000h
DB 000h,000h,0CCh,0CCh,0CCh,0CCh,076h,000h
DB 000h,000h,0CCh,0CCh,0CCh,078h,030h,000h
DB 000h,000h,0C6h,0D6h,0FEh,0FEh,06Ch,000h
DB 000h,000h,0C6h,06Ch,038h,06Ch,0C6h,000h
DB 000h,000h,0CCh,0CCh,0CCh,07Ch,00Ch,0F8h
DB 000h,000h,0FCh,098h,030h,064h,0FCh,000h
DB 01Ch,030h,030h,0E0h,030h,030h,01Ch,000h
DB 018h,018h,018h,000h,018h,018h,018h,000h
DB 0E0h,030h,030h,01Ch,030h,030h,0E0h,000h
DB 076h,0DCh,000h,000h,000h,000h,000h,000h
DB 000h,010h,038h,06Ch,0C6h,0C6h,0FEh,000h
DB 078h,0CCh,0C0h,0CCh,078h,018h,00Ch,078h
DB 000h,0CCh,000h,0CCh,0CCh,0CCh,07Eh,000h
DB 01Ch,000h,078h,0CCh,0FCh,0C0h,078h,000h
DB 07Eh,0C3h,03Ch,006h,03Eh,066h,03Fh,000h
DB 0CCh,000h,078h,00Ch,07Ch,0CCh,07Eh,000h
DB 0E0h,000h,078h,00Ch,07Ch,0CCh,07Eh,000h
DB 030h,030h,078h,00Ch,07Ch,0CCh,07Eh,000h
DB 000h,000h,078h,0C0h,0C0h,078h,00Ch,038h
DB 07Eh,0C3h,03Ch,066h,07Eh,060h,03Ch,000h
DB 0CCh,000h,078h,0CCh,0FCh,0C0h,078h,000h
DB 0E0h,000h,078h,0CCh,0FCh,0C0h,078h,000h
DB 0CCh,000h,070h,030h,030h,030h,078h,000h
DB 07Ch,0C6h,038h,018h,018h,018h,03Ch,000h
DB 0E0h,000h,070h,030h,030h,030h,078h,000h
DB 0C6h,038h,06Ch,0C6h,0FEh,0C6h,0C6h,000h
DB 030h,030h,000h,078h,0CCh,0FCh,0CCh,000h
DB 01Ch,000h,0FCh,060h,078h,060h,0FCh,000h
DB 000h,000h,07Fh,00Ch,07Fh,0CCh,07Fh,000h
DB 03Eh,06Ch,0CCh,0FEh,0CCh,0CCh,0CEh,000h
DB 078h,0CCh,000h,078h,0CCh,0CCh,078h,000h
DB 000h,0CCh,000h,078h,0CCh,0CCh,078h,000h
DB 000h,0E0h,000h,078h,0CCh,0CCh,078h,000h
DB 078h,0CCh,000h,0CCh,0CCh,0CCh,07Eh,000h
DB 000h,0E0h,000h,0CCh,0CCh,0CCh,07Eh,000h
DB 000h,0CCh,000h,0CCh,0CCh,07Ch,00Ch,0F8h
DB 0C3h,018h,03Ch,066h,066h,03Ch,018h,000h
DB 0CCh,000h,0CCh,0CCh,0CCh,0CCh,078h,000h
DB 018h,018h,07Eh,0C0h,0C0h,07Eh,018h,018h
DB 038h,06Ch,064h,0F0h,060h,0E6h,0FCh,000h
DB 0CCh,0CCh,078h,0FCh,030h,0FCh,030h,030h
DB 0F8h,0CCh,0CCh,0FAh,0C6h,0CFh,0C6h,0C7h
DB 00Eh,01Bh,018h,03Ch,018h,018h,0D8h,070h
DB 01Ch,000h,078h,00Ch,07Ch,0CCh,07Eh,000h
DB 038h,000h,070h,030h,030h,030h,078h,000h
DB 000h,01Ch,000h,078h,0CCh,0CCh,078h,000h
DB 000h,01Ch,000h,0CCh,0CCh,0CCh,07Eh,000h
DB 000h,0F8h,000h,0F8h,0CCh,0CCh,0CCh,000h
DB 0FCh,000h,0CCh,0ECh,0FCh,0DCh,0CCh,000h
DB 03Ch,06Ch,06Ch,03Eh,000h,07Eh,000h,000h
DB 038h,06Ch,06Ch,038h,000h,07Ch,000h,000h
DB 030h,000h,030h,060h,0C0h,0CCh,078h,000h
DB 000h,000h,000h,0FCh,0C0h,0C0h,000h,000h
DB 000h,000h,000h,0FCh,00Ch,00Ch,000h,000h
DB 0C3h,0C6h,0CCh,0DEh,033h,066h,0CCh,00Fh
DB 0C3h,0C6h,0CCh,0DBh,037h,06Fh,0CFh,003h
DB 018h,018h,000h,018h,018h,018h,018h,000h
DB 000h,033h,066h,0CCh,066h,033h,000h,000h
DB 000h,0CCh,066h,033h,066h,0CCh,000h,000h
DB 022h,088h,022h,088h,022h,088h,022h,088h
DB 055h,0AAh,055h,0AAh,055h,0AAh,055h,0AAh
DB 0DBh,077h,0DBh,0EEh,0DBh,077h,0DBh,0EEh
DB 018h,018h,018h,018h,018h,018h,018h,018h
DB 018h,018h,018h,018h,0F8h,018h,018h,018h
DB 018h,018h,0F8h,018h,0F8h,018h,018h,018h
DB 036h,036h,036h,036h,0F6h,036h,036h,036h
DB 000h,000h,000h,000h,0FEh,036h,036h,036h
DB 000h,000h,0F8h,018h,0F8h,018h,018h,018h
DB 036h,036h,0F6h,006h,0F6h,036h,036h,036h
DB 036h,036h,036h,036h,036h,036h,036h,036h
DB 000h,000h,0FEh,006h,0F6h,036h,036h,036h
DB 036h,036h,0F6h,006h,0FEh,000h,000h,000h
DB 036h,036h,036h,036h,0FEh,000h,000h,000h
DB 018h,018h,0F8h,018h,0F8h,000h,000h,000h
DB 000h,000h,000h,000h,0F8h,018h,018h,018h
DB 018h,018h,018h,018h,01Fh,000h,000h,000h
DB 018h,018h,018h,018h,0FFh,000h,000h,000h
DB 000h,000h,000h,000h,0FFh,018h,018h,018h
DB 018h,018h,018h,018h,01Fh,018h,018h,018h
DB 000h,000h,000h,000h,0FFh,000h,000h,000h
DB 018h,018h,018h,018h,0FFh,018h,018h,018h
DB 018h,018h,01Fh,018h,01Fh,018h,018h,018h
DB 036h,036h,036h,036h,037h,036h,036h,036h
DB 036h,036h,037h,030h,03Fh,000h,000h,000h
DB 000h,000h,03Fh,030h,037h,036h,036h,036h
DB 036h,036h,0F7h,000h,0FFh,000h,000h,000h
DB 000h,000h,0FFh,000h,0F7h,036h,036h,036h
DB 036h,036h,037h,030h,037h,036h,036h,036h
DB 000h,000h,0FFh,000h,0FFh,000h,000h,000h
DB 036h,036h,0F7h,000h,0F7h,036h,036h,036h
DB 018h,018h,0FFh,000h,0FFh,000h,000h,000h
DB 036h,036h,036h,036h,0FFh,000h,000h,000h
DB 000h,000h,0FFh,000h,0FFh,018h,018h,018h
DB 000h,000h,000h,000h,0FFh,036h,036h,036h
DB 036h,036h,036h,036h,03Fh,000h,000h,000h
DB 018h,018h,01Fh,018h,01Fh,000h,000h,000h
DB 000h,000h,01Fh,018h,01Fh,018h,018h,018h
DB 000h,000h,000h,000h,03Fh,036h,036h,036h
DB 036h,036h,036h,036h,0FFh,036h,036h,036h
DB 018h,018h,0FFh,018h,0FFh,018h,018h,018h
DB 018h,018h,018h,018h,0F8h,000h,000h,000h
DB 000h,000h,000h,000h,01Fh,018h,018h,018h
DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
DB 000h,000h,000h,000h,0FFh,0FFh,0FFh,0FFh
DB 0F0h,0F0h,0F0h,0F0h,0F0h,0F0h,0F0h,0F0h
DB 00Fh,00Fh,00Fh,00Fh,00Fh,00Fh,00Fh,00Fh
DB 0FFh,0FFh,0FFh,0FFh,000h,000h,000h,000h
DB 000h,000h,076h,0DCh,0C8h,0DCh,076h,000h
DB 000h,078h,0CCh,0F8h,0CCh,0F8h,0C0h,0C0h
DB 000h,0FCh,0CCh,0C0h,0C0h,0C0h,0C0h,000h
DB 000h,0FEh,06Ch,06Ch,06Ch,06Ch,06Ch,000h
DB 0FCh,0CCh,060h,030h,060h,0CCh,0FCh,000h
DB 000h,000h,07Eh,0D8h,0D8h,0D8h,070h,000h
DB 000h,066h,066h,066h,066h,07Ch,060h,0C0h
DB 000h,076h,0DCh,018h,018h,018h,018h,000h
DB 0FCh,030h,078h,0CCh,0CCh,078h,030h,0FCh
DB 038h,06Ch,0C6h,0FEh,0C6h,06Ch,038h,000h
DB 038h,06Ch,0C6h,0C6h,06Ch,06Ch,0EEh,000h
DB 01Ch,030h,018h,07Ch,0CCh,0CCh,078h,000h
DB 000h,000h,07Eh,0DBh,0DBh,07Eh,000h,000h
DB 006h,00Ch,07Eh,0DBh,0DBh,07Eh,060h,0C0h
DB 038h,060h,0C0h,0F8h,0C0h,060h,038h,000h
DB 078h,0CCh,0CCh,0CCh,0CCh,0CCh,0CCh,000h
DB 000h,0FCh,000h,0FCh,000h,0FCh,000h,000h
DB 030h,030h,0FCh,030h,030h,000h,0FCh,000h
DB 060h,030h,018h,030h,060h,000h,0FCh,000h
DB 018h,030h,060h,030h,018h,000h,0FCh,000h
DB 00Eh,01Bh,01Bh,018h,018h,018h,018h,018h
DB 018h,018h,018h,018h,018h,0D8h,0D8h,070h
DB 030h,030h,000h,0FCh,000h,030h,030h,000h
DB 000h,076h,0DCh,000h,076h,0DCh,000h,000h
DB 038h,06Ch,06Ch,038h,000h,000h,000h,000h
DB 000h,000h,000h,018h,018h,000h,000h,000h
DB 000h,000h,000h,000h,018h,000h,000h,000h
DB 00Fh,00Ch,00Ch,00Ch,0ECh,06Ch,03Ch,01Ch
DB 078h,06Ch,06Ch,06Ch,06Ch,000h,000h,000h
DB 070h,018h,030h,060h,078h,000h,000h,000h
DB 000h,000h,03Ch,03Ch,03Ch,03Ch,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h
;----------------------------------------------------------------------------+
Debugging = 0
@BreakPoint MACRO
IFE Debugging
Debugging = 1
IF1
%OUT *** Debugging activated ***
ENDIF
ENDIF
call BreakPoint
ENDM
@MarkOn MACRO
IFE Debugging
Debugging = 1
IF1
%OUT *** Debugging activated ***
ENDIF
ENDIF
call MarkOn
ENDM
@MarkOff MACRO
IFE Debugging
Debugging = 1
IF1
%OUT *** Debugging activated ***
ENDIF
ENDIF
call MarkOff
ENDM
;----------------------------------------------------------------------------+
ComputeWrapPos MACRO PointerReg ;DL=BytesToMove.
LOCAL NoWrapping,GotWrapPos
mov ah,dl
mov cx,2000h
sub cx,PointerReg ;CX = Distanz bis zum Wrap.
test ch,ch ;Distanz >= 256 Bytes?
jnz NoWrapping ;=> In dieser Zeile kein Wrap.
cmp cl,dl ;Distanz >= BytesToMove?
jb GotWrapPos ;Dann ebenfalls kein Wrap.
NoWrapping:
mov cl,dl ;In diesem Fall
mov ch,0 ;CX=ganze Window-Zeile.
GotWrapPos:
sub ah,cl ;Wieviel bleibt dann noch übrig?
ENDM ;CX=Anz MOVSB's vor dem Page-Wrap, AH=Anz dannach.
UpdateCursorPos PROC NEAR ;AX=CursorPos, wird direkt in den Chip geschickt.
push dx ;Register retten.
mov dx,ax
DisplayAdress_Text dl,dh
push ax ;DisplayAdresse merken.
mov dx,IndexReg
mov al,15
out dx,al ;Select Reg 15
inc dx
pop ax ;DisplayAdresse zurückholen
out dx,al ;und Low Byte schreiben
dec dx
mov al,14
out dx,al ;Select Reg 14
inc dx
mov al,ah
out dx,al ;und High Byte schreiben.
pop dx
ret
UpdateCursorPos ENDP ;AX destroyed.
UpdateDispStart PROC NEAR ;AX=neuer DispStart, DS=40h
mov CurDispStart,ax
push dx
shr ax,1 ;Offset in Words berechnen
push ax ;und merken.
mov dx,IndexReg
mov al,13
out dx,al ;RegisterNr ins IndexReg
inc dx
pop ax ;DisplayPosition nach AX
out dx,al ;und LowByte ins DataReg.
dec dx
mov al,12 ;HighByte: Zuerst RegNr
out dx,al ;ins IndexReg
inc dx
mov al,ah ;und dann das DatenByte
out dx,al ;ins DataReg.
pop dx
ret
UpdateDispStart ENDP ;AX destroyed
ScrollPartOfScreenUp PROC NEAR
;AL=NrOfLines, (CH/CL)-(DH/DL), BL=New Attribute, AH=CurVideoMode, BH=PageNr
push cx ;Register retten.
push dx
push bx
sub dx,cx ;WindowGröße berechnen.
add dx,0101h
cmp al,0 ;NrOfLines=0? => Window soll nicht
je NowClearWindow ;gescrolled sondern gelöscht werden.
cmp al,dh ;NrOfLines>=WinSize?
jae NowClearWindow ;Dann das ganze Window löschen.
mov bl,al
cmp ah,7 ;Sind wir im Text-Mode?
je DoScrolling0 ;Dann ist es ja einfach.
cmp cs:FastScrollFlag,True ;Soll IMMER langsam gescrolled werden?
jne DoScrolling0 ;Auch in Ordnung.
mov al,dl ;Wieviele Zeichen enthält das Window,
mul dh ;das gescrolled werden soll?
cmp ax,WholeScr*2/3 ;Weniger als 2/3 des ganzen Screens?
jb DoScrolling0 ;Dann ebenfalls direkt scrollen.
nop ;Es soll also FastScrolling gemacht werden. Ok!
add ch,dh ;(YPos ist für alle Bereiche gleich,
push cx ;nämlich die erste Zeile unter
push dx ;dem zu scrollenden Window...)
mov dl,cl
mov cl,0
mov dh,NrOfLines
call RotateWindowDown ;Bereich 2,
mov cl,dl
pop dx
neg dh
add dh,NrOfLines
add dh,bl
call RotateWindowDown ;Bereich 3 und
add cl,dl
mov dl,NrOfChars
sub dl,cl
mov dh,NrOfLines
call RotateWindowDown ;Bereich 4 entgegengesetzt rotieren.
test bh,1
GetPageArrayIndex OFFSET(DispStartTable),si ;Um welche Page geht es?
mov ax,cs:[si]
add ax,2*NrOfChars ;Entsprechenden DispStart
and ax,1FFFh ;um 2 Scans (je 4 Dots hoch)
mov cs:[si],ax ;hochsetzen und
cmp bh,ActivePage
jne NoDisplayUpdate0 ;Wurde die active Page gescrolled?
call UpdateDispStart ;Dann neue DispStart auch an den 6845 schicken.
NoDisplayUpdate0:
pop ax
mov cl,al ;Alte XPosLo wiederholen,
sub ch,bl ;CH = YPosLo der nach Einscrollen zu löschenden Zeilen.
neg dl
add dl,NrOfChars ;(DH/DL) = Größe des nach Einscrollen
sub dl,cl ;zu löschenden Bereichs.
mov dh,bl
jmp SHORT NowClearWindow
DoScrolling0: ;BL=NrOfLines, (CH/CL)=Upper Left, (DH/DL)=Size of Window
call RotateWindowUp
add ch,dh ;Die neu eingescrollten Zeilen müssen noch gelöscht werden,
sub ch,bl ;und zwar vom unteren Ende des zu scrollenden Bereichs an
mov dh,bl ;so viele Zeilen, wie das Window gescrolled wurde.
NowClearWindow: ;CX=WindowStart, DX=WindowSize
pop bx ;"NewAttrib" und "PageNr" für
call ClearWindow ;"ClearWindow" zurückholen.
pop dx
pop cx
ret
ScrollPartOfScreenUp ENDP ;AX and SI destroyed.
ScrollPartOfScreenDown PROC NEAR
;AL=NrOfLines, (CH/CL)-(DH/DL), BL=New Attribute, AH=CurVideoMode, BH=PageNr
push cx ;Register retten.
push dx
push bx
sub dx,cx ;WindowGröße berechnen.
add dx,0101h
cmp al,0 ;NrOfLines=0? => Window soll nicht
je NowClearWindow ;gescrolled sondern gelöscht werden.
cmp al,dh ;NrOfLines>=WinSize?
jae NowClearWindow ;Dann das ganze Window löschen.
mov bl,al
cmp ah,7 ;Sind wir im Text-Mode?
je DoScrolling1 ;Dann ist es ja einfach.
cmp cs:FastScrollFlag,True ;Soll IMMER langsam gescrolled werden?
jne DoScrolling1 ;Auch in Ordnung.
mov al,dl ;Wieviele Zeichen enthält das Window,
mul dh ;das gescrolled werden soll?
cmp ax,WholeScr*2/3 ;Weniger als 2/3 des ganzen Screens?
jb DoScrolling1 ;Dann ebenfalls direkt scrollen.
nop
add ch,dh ;Es soll also FastScrolling gemacht werden. Ok!
sub ch,bl ;(YPos ist für alle Bereiche gleich...)
push dx
add cl,dl
mov dl,NrOfChars
sub dl,cl
mov dh,NrOfLines
call RotateWindowUp ;Bereich 4,
pop dx
push dx
sub cl,dl
neg dh
add dh,NrOfLines
add dh,bl
call RotateWindowUp ;Bereich 3 und
mov dl,cl
mov cl,0
mov dh,NrOfLines
call RotateWindowUp ;Bereich 2 entgegengesetzt rotieren.
test bh,1
GetPageArrayIndex OFFSET(DispStartTable),si ;Um welche Page geht es?
mov ax,cs:[si]
sub ax,2*NrOfChars ;Entsprechenden DispStart
and ax,1FFFh ;um 2 Scans (je 4 Dots hoch)
mov cs:[si],ax ;zurücksetzen und
cmp bh,ActivePage
jne NoDisplayUpdate1 ;Wurde die active Page gescrolled?
call UpdateDispStart ;Dann neue DispStart auch an den 6845 schicken.
NoDisplayUpdate1:
mov cl,dl
pop dx ;(CL/CH) - (DL/DH)
sub ch,dh
add ch,bl ; = nach dem Einscrollen
mov dh,bl ;zu löschender Bereich.
jmp NowClearWindow
DoScrolling1: ;BL=NrOfLines, (CH/CL)=Upper Left, (DH/DL)=Size of Window
call RotateWindowDown
mov dh,bl ;Die oben neu eingescrollten Zeilen
jmp NowClearWindow ;müssen noch gelöscht werden.
ScrollPartOfScreenDown ENDP ;AX and SI destroyed.
RotParamCheck PROC NEAR
cmp dh,1 ;Sollen 0 oder 1 Zeile rotiert werden?
jbe NoRotation ;Brauchen wir gar nicht mit anfangen.
cmp dl,0 ;Ist das Window so schmal?
je NoRotation ;Dann sind wir schon fertig.
mov al,bl
RangeParam:
sub al,dh ;Soll das Window um mehr Zeilen rotiert werden als es
ja RangeParam ;hoch ist? Dann BL in den richtigen Bereich bringen.
add al,dh ;Vorhin wurde einmal zu oft abgezogen: korrigeren.
;cmp al,0 ;Soll um 0 Zeilen rotiert werden?
;je NoRotation <-- überflüssig... ;=> Fertig.
mov bl,al
mov al,dh ;Soll das Window um
shr al,1 ;mehr als die Hälfte
cmp bl,al ;rotiert werden?
ja ScrollReverse ;Dann lieber andersrum rotieren.
clc ;Params ok,
ret ;mit C=0 zurück.
ScrollReverse: ;Window soll andersrum rotiert werden.
neg bl ;Rotation-Count an neue Drehrichtung anpassen:
add bl,dh ;BL := DH - BL.
ret ;Mit C=1 zurück.
NoRotation: ;Es gibt nichts zu tun?
add sp,2 ;Dann Rückkehradresse auf dem Stack verwerfen
ret ;und zurück zur übergeordneten Routine.
RotParamCheck ENDP ;AL destroyed.
RotateWindowUp PROC NEAR
;BL=NrOfLines, CX=UpperLeft, DX=Size of Window, BH=PageNr.
call RotParamCheck ;Sind die Parameter in Ordnung?
jc RotateWindowDown ;Eignen sie sich besser für "RotateDown"?
push bx
push cx
push bp ;Register retten.
push di
push ds
push es
test bh,1 ;Welches Page betrifft es denn?
GetPageArrayIndex 0,si
cmp CurVideoMode,8 ;Sind wir im Graphik-Modus?
mov ds,cs:[PageSegment+si] ;DS = SEG(ActivePage),
je GraphRotation0 ;Dann andere Rotation-Routine benutzen.
nop
DisplayAdress_Text cl,ch ;DisplayAdresse
shl ax,1 ;mal 2 Bytes pro Char
mov si,ax ;=> DS:SI = StartAdresse.
mov bp,+160
call RotateTextWindow
jmp SHORT RotationDone0
GraphRotation0: ;Also Graphik-Modus.
push dx ;Dann erst noch ein weiteres Register retten.
shl bl,1 ;BL (NrOfLines), CH (WinYLo) und DH (WinHeight)
shl ch,1 ;von ZeichenZeilen (je 8 Dots hoch) nach
shl dh,1 ;ScanZeilen (je 4 Dots hoch) umrechnen.
DisplayAdress_Graph cl,ch
mov si,cs:[DispStartTable+si] ;DisplayAdress
add si,ax ; + DispStart
and si,1FFFh ;nach Begrenzung
mov bp,+NrOfDotsX/8 ;=> DS:SI = StartAdresse.
mov bh,NrOfDotsY/4
sub bh,ch ;BH = Anz ScanLines (je 4 Dots hoch) bis zum BottomOfScreen.
call RotateBitMap ;Erste BitMap (Segment-Offset 0000h),
call RotateBitMap ;zweite BitMap (Offset 2000h),
call RotateBitMap ;dritte (Offset 4000h)
call RotateBitMap ;und vierte (Offset 6000h) seperat rotieren.
pop dx
RotationDone0:
pop es
pop ds
pop di ;Gerettete Register zurückholen
pop bp
pop cx
pop bx
ret ;und fertig.
RotateWindowUp ENDP ;AX and SI destroyed.
RotateWindowDown PROC NEAR
;BL=NrOfLines, CX=UpperLeft, DX=Size of Window, BH=PageNr.
call RotParamCheck ;Sind die Parameter in Ordnung?
jc RotateWindowUp ;Eignen sie sich besser für "RotateUp"?
push bx
push cx
push bp
push di ;Register retten.
push ds
push es
add ch,dh ;*) Rotation muß in der letzten Zeile beginnen
dec ch ;(und nicht in der ersten).
test bh,1 ;Welches ist die betroffene Page?
GetPageArrayIndex 0,si
cmp CurVideoMode,8
mov ds,cs:[PageSegment+si] ;DS = SEG(ConcernedPage),
je GraphRotation1 ;Im GraphikModus andere Rotation-Routine benutzen.
nop
cmp ch,25 ;ACHTUNG! Durch den Befehl "ADD CH,DH" bei *)
jb NoScreenWrap_Text ;ist möglicherweise ein ScreenWrap entstanden!
sub ch,25
NoScreenWrap_Text:
DisplayAdress_Text cl,ch ;DisplayAdresse
shl ax,1 ;mal 2 Bytes pro Char
mov si,ax ;=> DS:SI = StartAdresse.
mov bp,-160
call RotateTextWindow
jmp SHORT RotationDone1
GraphRotation1: ;Also Graphik-Modus.
push dx ;Dann erst noch ein weiteres Register retten.
cmp ch,NrOfLines
jb NoScreenWrap_Graph ;Dasselbe wie oben, nur diesmal im GraphMode.
sub ch,NrOfLines
NoScreenWrap_Graph:
shl bl,1
shl ch,1 ;BL, CH und DH in Scan-Lines umrechnen (*2),
inc ch ;CH dabei an das UNTERE Ende der TextZeile setzen.
shl dh,1
DisplayAdress_Graph cl,ch
mov si,cs:[DispStartTable+si] ;DisplayAdress
add si,ax ; + DispStart
and si,1FFFh ;nach Begrenzung
mov bp,-NrOfDotsX/8 ;=> DS:SI = StartAdresse.
mov bh,ch
inc bh ;BH = Anz ScanLines bis zum TopOfScreen.
call RotateBitMap ;Erste BitMap (Segment-Offset 0000h),
call RotateBitMap ;zweite BitMap (Offset 2000h),
call RotateBitMap ;dritte (Offset 4000h)
call RotateBitMap ;und vierte (Offset 6000h) seperat rotieren.
pop dx
RotationDone1:
pop es
pop ds
pop di
pop bp ;Gerettete Register zurückholen.
pop cx
pop bx
ret
RotateWindowDown ENDP ;AX and SI destroyed.
RotateTextWindow PROC NEAR
;BP = Byte-Distanz zur nächsten Zeile (+ oder - 160 Bytes, je nach Richtung)
;DS:SI = Adresse der ersten zu bearbeitenden Zeile.
;BL = Um wie viele Zeilen,
;DL = wie viele Zeichen pro Zeile, und
;DH = wie viele Zeilen rotiert werden sollen.
cld
mov di,cs
mov es,di
mov di,OFFSET RotateBuffer ;[ES:DI] = RotateBuffer.
mov al,bl ;AL = MoveLine-Count.
mov ch,0
push si ;"StartAdresse" für später merken.
NextLineIntoBuffer:
push si
mov cl,dl
rep movsw
pop si
add si,bp
dec al
jnz NextLineIntoBuffer
nop
mov di,ds
mov es,di
pop di ;ES:DI = StartAdresse.
mov al,dh
sub al,bl ;AL = MoveLine-Count.
NextLine:
push si
push di
mov cl,dl
rep movsw
pop di
pop si
add di,bp
add si,bp
dec al
jnz NextLine
nop
mov si,cs
mov ds,si
mov si,OFFSET RotateBuffer ;[DS:SI] = RotateBuffer.
mov al,bl ;AL = MoveLine-Count.
NextLineFromBuffer:
push di
mov cl,dl
rep movsw
pop di
add di,bp
dec al
jnz NextLine
ret
RotateTextWindow ENDP ;AX, CX, SI, DI, DS, and ES destroyed.
RotateBitMap PROC NEAR
;BP = Byte-Distanz zur nächsten Zeile (+ oder - 90 Bytes, je nach Richtung)
;DS:SI = Adresse der ersten zu bearbeitenden Zeile.
;BH = Wie viele Scan-Lines bis zum ScreenWrap.
;BL = Um wie viele ScanLines,
;DL = wie viele Bytes pro ScanLine, und
;DH = wie viele ScanLines rotiert werden sollen.
;!!! ACHTUNG, BH muß kleiner oder gleich BL sein !!!
cld
push bx ;Register retten.
push si
mov al,bl ;AL = MoveLine-Count.
mov di,cs
mov es,di
mov di,OFFSET RotateBuffer ;[ES:DI] = RotateBuffer.
push si ;BX und "StartAdress" für später merken.
MoveLineIntoBuffer:
ComputeWrapPos si ;CX = Wieviele Bytes können OHNE Page-Wrap ver-
push si ;schoben werden, AH = wieviele Bytes sind übrig.
rep movsb ;Ersten Teil bis zum Page-Wrap verschieben,
xor si,si ;dann Zeiger auf den Anfang der Page zurücksetzen
mov cl,ah ;und den Rest der Zeile verschieben.
rep movsb
pop si
add si,bp
dec al ;Müssen noch Zeilen verschoben werden?
jnz MoveLineIntoBuffer
nop
mov di,ds
mov es,di
pop di ;ES:DI = StartAdress (Dest).
mov al,dh
sub al,bl ;AL = MoveLine-Count.
sub bh,bl ;BH = ScreenWrap-Count (Source).
inc bh ;schon mal inkrementieren,
sub si,bp
MoveLine: ;es wird nämlich gleich wieder dekrementiert --+
add si,bp ; !
dec bh ; <-----+
jnz NoScreenWrap ;Hat ein ScreenWrap stattgefunden?
mov bh,NrOfDotsY/4-1 ;Dann neu ansetzen:
test bp,bp ;Sind wir am UNTEREN oder am OBEREN Ende?
js SetToBottom
sub si,ScrSize/4 ;Am unteren? Dann auf das obere setzen und
add di,(8000h-ScrSize)/4 ;DI für neuen DispStart korrigieren.
jmp SHORT NoScreenWrap
SetToBottom:
add si,ScrSize/4 ;Am oberen? Dann auf das untere setzen und
sub di,(8000h-ScrSize)/4 ;DI für neuen DispStart korrigieren.
NoScreenWrap:
and si,1FFFh
and di,1FFFh
ComputeWrapPos si
test ah,ah ;Kommt in dieser SOURCE-Zeile ein Wrap vor?
jnz NoSourceWrap
ComputeWrapPos di ;Nicht? Dann vielleicht in dieser DEST-Zeile.
NoSourceWrap:
push si
push di
rep movsb ;Ersten Teil der Zeile (bis zum PageWrap) verschieben.
and si,1FFFh ;Da ich nicht weiß, WELCHES der beiden IndexRegs den
and di,1FFFh ;Wrap verursacht hat, werden einfach beide zurückgesetzt.
mov cl,ah
rep movsb
pop di
pop si
add di,bp ;DI eine Zeile weitersetzen und
dec al ;MoveLine-Count dekrementieren.
jnz MoveLine
nop
mov si,cs
mov ds,si
mov si,OFFSET RotateBuffer ;[DS:SI] = RotateBuffer.
MoveLineFromBuffer:
ComputeWrapPos di
push di
rep movsb
xor di,di
mov cl,ah
rep movsb
pop di
add di,bp
and di,1FFFh
dec bl
jnz MoveLineFromBuffer
nop
mov cx,es
add cx,200h ;DS schon mal auf die nächste BitMap setzen
mov ds,cx
pop si
pop bx ;und Register wieder herstellen.
ret
RotateBitMap ENDP ;AX, CX, DI, and ES destroyed, DS:=DS+0200h.
ClearWindow PROC NEAR ;BL=NewAttrib, BH=PageNr, CX=Window Start, DX=WinSize
push di ;Register retten.
test bh,1 ;In welcher Page soll gelöscht werden?
GetPageArrayIndex OFFSET(CursPosTable),di
push [di] ;Entsprechende CursorPos pushen und
mov [di],cx ;statt dessen die Pos des Windows dorthin schreiben.
mov cl,dl ;"NrOfChars" setzen.
mov ch,0
ClearNextLine:
cmp dh,0 ;War das die letzte Zeile?
je ClearDone ;Dann fertig.
mov al,' '
mov ah,CurVideoMode ;(AH muß den momentanen VideoMode enthalten)
call WriteAttrChar ;Sonst eine Zeile mit Spaces füllen (=löschen).
inc byte ptr [di+1] ;CursorPos.YPos im BiosSegment eine Zeile
dec dh ;weitersetzen und ZeilenCount dekrementieren.
jmp SHORT ClearNextLine ;Nächste Zeile bearbeiten.
ClearDone:
pop [di] ;Alte CursorPos wieder herstellen,
pop di ;Register zurückholen
ret ;und zurück zum Caller.
ClearWindow ENDP ;AX, CX, DX, and SI destroyed.
ComputeDotAdress PROC NEAR ;CX=XPos, DX=YPos, ZF=PageNr.
GetPageArrayIndex 0,bx
mov es,cs:[PageSegment+bx] ;Entsprechende Werte für
mov bx,cs:[DispStartTable+bx] ;Seg und Ofs dieser Page holen.
ror dx,1 ;YPos von Dots in Scans
ror dx,1 ;(je 4 Punkte hoch) umrechnen.
mov al,90 ;ScanNr mal 90 Bytes per Scan
mul dl ;ergibt den Offset der Zeile
add bx,ax ;(relativ zum DispStart).
mov ax,cx
shr ax,1 ;Jetzt noch den Byte-Offset
shr ax,1 ;innerhalb der Zeile berechnen
shr ax,1 ;(XPos SHR 3)
add bx,ax ;und ebenfalls dazuaddieren.
and bh,1Fh ;BX auf eine BitMap begrenzen!
shr dh,1 ;Jetzt noch die entsprechende BitMap
or bh,dh ;über ihre BasisAdresse selektieren.
and cl,7
ret
ComputeDotAdress ENDP ;ES:BX=DotAdress, CL=BitNr. AX and DX destroyed.
HandleBeep PROC NEAR ;BH=PageNr, [DS:SI]=CursorPos im BiosSegment.
cmp bh,ActivePage ;Soll es in einer anderen als der aktiven
jne BeepDone ;Page piepen? Dann lassen wir das lieber.
mov ah,14 ;Function "TeletypeOut"
mov al,7 ;mit AL=Bel
pushf ;des alten (!)
call dword ptr cs:[SavedInt10Vec] ;INT10-Handlers aufrufen.
BeepDone:
mov ax,[si]
ret
HandleBeep ENDP ;AX=neue CursorPos.
HandleReturn PROC NEAR ;BH=PageNr, [DS:SI]=CursorPos im BiosSegment.
mov ax,[si]
mov al,0
mov [si],ax
ret
HandleReturn ENDP ;AX=neue CursorPos.
HandleLinefeed PROC NEAR ;BH=PageNr, [DS:SI]=CursorPos im BiosSegment.
mov ax,[si] ;CursorPos holen und testen:
cmp ah,LastTextLine ;Sind wir auf der letzten Zeile?
je ScrollOneLineUp ;Dann ist eine extra-Behandlung nötig,
inc ah ;sonst Cursor einfach eine Zeile
mov [si],ax ;tiefer setzen, neue Pos
ret
ScrollOneLineUp:
push ax
push bx
push cx
push dx
mov ah,CurVideoMode ;In der betroffenen DisplayPage das
call ReadAttrChar ;Attrib des Zeichens an der CursorPos
mov bl,ah ;holen und mit diesem Attribute
mov al,1 ;die eine Zeile füllen,
mov ah,CurVideoMode ;die entsteht,
mov cx,0 ;wenn das Window oben links
mov dl,byte ptr NrOfColumns ;bis ganz unten rechts
dec dl ;(also der ganze Screen)
mov dh,LastTextLine ;der betroffenen Page
call ScrollPartOfScreenUp ;hochgescrolled wird.
pop dx
pop cx ;Register wieder herstellen
pop bx
pop ax
ret ;und fertig.
HandleLinefeed ENDP ;AX=neue CursorPos, SI destroyed.
HandleBackspace PROC NEAR ;BH=PageNr, [DS:SI]=CursorPos im BiosSegment.
mov ax,[si] ;Wo steht der Cursor z.Z.?
cmp al,0 ;Auf der ersten Spalte und soll ein Zeichen zurück?
IF BsLineUp
je BackspaceDone ;Dann BackSpace ignorieren
ELSE
jne SetCursorBack
cmp ah,0 ;oder,
je BackspaceDone ;wenn Cursor nicht schon in Home-Position,
dec ah ;eine Zeile höher
mov al,byte ptr NrOfColumns ;auf das letzte Zeichen setzen.
SetCursorBack:
ENDIF
dec al
mov [si],ax ;Neue Cursor-Position speichern.
BackspaceDone:
ret
HandleBackspace ENDP ;AX=neue CursorPos.
WriteOneChar PROC NEAR ;AL=Char, BL=Attrib, BH=PageNr, [DS:SI]=CursorPos.
cmp al,7
je HandleBeep ;Bel,
cmp al,13
je HandleReturn ;Cr,
cmp al,10
je HandleLineFeed ;Lf und
cmp al,8
je HandleBackspace ;Bs separat behandeln,
push cx ;alle anderen Zeichen
push si ;als 'Printables' verarbeiten:
mov cx,1 ;Ein Zeichen
mov ah,CurVideoMode ;im aktuellen Mode
call WriteAttrChar ;mit Attribute schreiben,
pop si
pop cx
mov ax,[si] ;Wo steht der Cursor JETZT?
inc al
mov [si],ax ;Ein Zeichen weiter nach rechts setzen
cmp al,byte ptr NrOfColumns ;und testen: Sind wir noch innerhalb
jne WriteOneCharDone ;der Zeile? Dann ist's ja gut.
call HandleReturn ;Sonst Cursor auf den Anfang
call HandleLineFeed ;der nächsten Zeile setzen.
WriteOneCharDone:
ret ;Achtung! CursorPos wird NICHT an den 6845 geschickt!
WriteOneChar ENDP ;AX=neue CursorPos, SI destroyed.
SendStringToPrinter PROC NEAR ;[CS:SI]=PascalString.
cld
lods byte ptr cs:[si] ;Längenbyte des
mov cl,al ;PascalStrings
mov ch,0 ;nach CX holen.
clc
jcxz SendStringDone ;String leer? Dann fertig, mit C=0 zurück.
mov dl,cs:PrinterNr
mov dh,0 ;Sonst PrinterNummer nach DX
SendByteLoop:
lods byte ptr cs:[si] ;und in einer Schleife ein Zeichen holen,
mov ah,0
int 17h ;mittels Bios ausgeben,
and ah,00111001b ;Status testen (OutOfPaper=False,
cmp ah,00010000b ;Selected=True, IOError=False und TimeOut=False?)
loope SendByteLoop ;Status ok? Dann nächstes Zeichen (falls vorhanden).
clc ;Schleife abgebrochen, woran lag's denn?
jz SendStringDone ;Bloß Stringende erreicht? Dann war's erfolgreich.
stc ;Sonst lag es wohl am Status. Mit C=1 zurück.
SendStringDone:
ret
SendStringToPrinter ENDP ;AX, CX, DX, and SI destroyed. C=1 wenn Fehler.
PrintTextScreen PROC NEAR ;AL=ActivePage
push bx
push cx
push dx ;Register retten.
push si
test al,1 ;Welche Page ist denn aktiv?
GetPageArrayIndex 0,si ;Diese Page soll auch gedruckt werden.
push [CursPosTable+si] ;Momentane CursorPos merken!
mov ds,cs:[PageSegment+si]
mov si,OFFSET PrnTextInit ;TextHardcopy-InitString
call SendStringToPrinter ;zum Drucker schicken.
jc PrintTextFinished ;Fehler? => Hardcopy abbrechen.
mov si,0 ;[DS:SI]=Active Page.
mov bx,0 ;LineCounter initialisieren.
PrintTextLineLoop:
mov ax,bx ;Cursor auf den Anfang der
call UpdateCursorPos ;z.Z. gedruckten Zeile setzen.
mov cx,80
mov dl,0
mov dh,cs:PrinterNr ;DX=Printer-Number.
cld
PrintTextCharLoop:
lods byte ptr ds:[si] ;Erstes Zeichen der Zeile holen,
inc si ;(Attribute überspringen)
mov ah,0
int 17h ;und an Drucker schicken.
and ah,00111001b
cmp ah,00010000b
loope PrintTextCharLoop ;Solange, bis Zeile zuende oder Fehler.
jnz PrintTextFinished ;Fehler (Drucker offline oder so)?
cmp cs:PrtScrActive,True ;Oder PrtScr durch erneuten Tastendruck
jne PrintTextFinished ;abgebrochen? Dann vorzeitig beenden.
inc bh
cmp bh,25
jne PrintTextLineLoop
PrintTextFinished:
mov si,OFFSET PrnTextExit ;TextHardcopy-ExitString
call SendStringToPrinter ;zum Drucker schicken.
pop ax ;Alte CursorPos wieder holen,
pop si
pop dx ;Register wieder herstellen und
pop cx
pop bx
call UpdateCursorPos ;Cursor auf seine alte Position zurücksetzen.
ret
PrintTextScreen ENDP ;AX and DS destroyed.
PrintGraphScreen PROC NEAR ;AL=ActivePage
push bx
push cx
push dx ;Register retten.
push si
push di
test al,1
GetPageArrayIndex 0,di ;Welche Page soll den gedruckt werden?
mov ds,cs:[PageSegment+di]
mov di,cs:[DispStartTable+di] ;[DS:DI]=DispStart dieser Page.
mov si,OFFSET PrnGraphInit ;GraphHardcopy-InitString
call SendStringToPrinter ;zum Drucker schicken.
jc PrintGraphFinished ;Fehler? => Hardcopy abbrechen.
mov bl,NrOfLines ;LineCounter initialisieren.
PrintGraphLineLoop:
mov si,OFFSET PrnLineStart
call SendStringToPrinter ;LineStart-String zum Drucker schicken.
mov cx,NrOfChars ;Counter für "CharsPerLine" setzen.
PrintGraphCharLoop:
cld
push cx ;CharCount merken.
mov bh,2 ;Jetzt werden 2 Scans (= 8 Dots = 1 Zeichen)
ConvertNextByte:
mov si,OFFSET PrtScr8x8Buffer ;konvertiert und in den Buffer übertragen:
inc si ;(LängenByte überspringen)
mov al,[di] ;Ein Byte aus dem Bildschirmspeicher holen,
xor al,0FFh ;invertieren (für Druck schwarz auf weiß)
mov cx,8 ;und die 8 Bits einzeln verteilen:
ConvertNextBit:
shl al,1 ;MSB des Graphik-Bytes in den Carry schieben
rcl byte ptr cs:[si],1 ;und von dort in das erste Drucker-Byte,
inc si ;dann nächstes Bit in das nächste Byte.
loop ConvertNextBit
add di,2000h ;Jetzt ist das nächste GraphikByte dran, das
jno ConvertNextByte ;liegt eine Zeile tiefer in der nächsten BitMap,
add di,NrOfChars ;aber nach 4 BitMaps einen Scan tiefer setzen.
and di,1FFFh ;Dabei den PageWrap beachten.
dec bh
jnz ConvertNextByte ;Schon beide Scans bearbeitet?
mov si,OFFSET PrtScr8x8Buffer ;Dann die konvertierten 8 Bytes
call SendStringToPrinter ;jetzt zum Drucker schicken.
add di,-2*NrOfChars+1 ;ScreenPointer auf das nächste Zeichen setzen,
pop cx ;CharCount wieder holen
loop PrintGraphCharLoop ;und nächstes Zeichen bearbeiten.
mov si,OFFSET PrnLineEnd
call SendStringToPrinter ;LineEnd-String zum Drucker schicken.
jc PrintGraphFinished ;Fehler (z.B. Printer Offline)
cmp cs:PrtScrActive,True ;oder PrtScr durch erneuten Tasten-
jne PrintGraphFinished ;druck abgebrochen? Dann beenden.
add di,NrOfChars ;Sonst ScreenPointer eine Zeile tiefer setzen,
dec bl ;ZeilenCount dekrementieren
jnz PrintGraphLineLoop ;und nächste Zeile drucken.
PrintGraphFinished:
mov si,OFFSET PrnGraphExit ;GraphHardcopy-ExitString
call SendStringToPrinter ;zum Drucker schicken.
pop di
pop si
pop dx ;Register wieder herstellen.
pop cx
pop bx
ret
PrintGraphScreen ENDP ;AX and DS destroyed.